#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <arpa/inet.h>
#include "common.h"
#include "platform_protocol.h"
#include "radar_protocol.h"
#include "config.h"
#include "video_protocol.h"
#include "log.h"
#include "fusion.h"
#include "../cJSON/cJSON.h"
#include <curl/curl.h>

#define MINI_PACKET_SIZE 6

int32_t g_pole_relay_count = 0;
static int32_t g_pole_distance = 1500;  // 150m

static const uint8_t event_type_map[] = {
    [0x1] = ABNORMAL_STOP_CAR,
    [0x2] = REVERSE_MOVE,
    [0x3] = OVERSPEED_OR_LOWSPEED,
    [0x4] = ABNOR_CHANGE,
    [0x5] = COMPRE_WIRE,
    [0x6] = OVERSPEED_OR_LOWSPEED,
    [0x8] = EMER_STOP,
    [0x9] = ACCELERATION,
    [0xa] = QUNE_WAIT,
    [0xb] = VEHICLE_COLLISION,
    [0xc] = SPILL,
    [0xd] = ABNORMAL_STOP_CAR,
    [0x11] = EMERGEMCY_LANE,
    [0x12] = ILL_PARTING,
    [0x13] = LANE_CHANGE,
    [0x21] = PERSON_DETECTION,
    [0x41] = BLOCK_II,
    [0x42] = QUNE_WAIT,
    [0x43] = BLOCK_I,
};

int way_type_to_platform(int way_type)
{
    switch (way_type) {
        case 1:
            return GO_LEFT;
        case 2:
            return GO_STRAIGHT;
        case 3:
            return GO_RIGHT;
        default:
            return GO_STRAIGHT;
    }
}

uint8_t plate_color_to_platform(int plate)  // 车牌颜色
{
    switch (plate) {
        case 1:
            return 3;  // 黄色
        case 2:
            return 1;  // 蓝色
        case 3:
            return 5;  // 黑色
        case 4:
            return 4;  // 白色
        case 5:
            return 2;  // 绿色
        case 6:
            return 6;  // 黄绿
        case 7:
            return 7;  // 渐变绿
        default:
            return 0;  // 无
    }
}

void get_device_id(uint8_t *dev_id, uint8_t dev_type)
{
    char fix[4] = {0x0C, 0x00, 0x00, 0x00};

    memset(dev_id, 0, 10);
    memcpy(dev_id, fix, sizeof(fix));
    if (dev_type == RADAR_INCOMING) {
        memcpy(dev_id + 4, g_config.in_radar_ip, 4);
    }
    else {
        memcpy(dev_id + 4, g_config.out_radar_ip, 4);
    }
}

uint32_t get_frame_id()
{
    static uint32_t frame_id = 0;
    return frame_id++;
}

size_t pack_platform_realtime_data(char *buffer, platform_protocol_mix_data_t *mix_data, size_t mix_num, uint8_t dev_type)
{
    platform_protocol_t *platform_data = (platform_protocol_t *)buffer;
    platform_protocol_mix_t *mix = (platform_protocol_mix_t *)platform_data->data;
    size_t data_len = 0;
    mix->frame_id = get_frame_id();
    mix->radar_num = 0;
    mix->video_num = 0;
    mix->mix_num = mix_num;
    memcpy(mix->mix_data, mix_data, mix_num * sizeof(platform_protocol_mix_data_t));
    platform_data->header = PLATFORM_PROTOCOL_HEADER;
    get_device_id(platform_data->dev_id, dev_type);
    get_platform_time_stamp(platform_data->time_stamp);
    platform_data->type = 0x01;
    data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_mix_t, mix_data) + sizeof(platform_protocol_mix_data_t) * mix_num;
    *(uint16_t *)(buffer + data_len) = PLATFORM_PROTOCOL_TAIL;
    return data_len + 2;
}

size_t pack_platform_relay_data(char *buffer, platform_protocol_pole_relay_data_t *relay_data, size_t relay_num)
{
    platform_protocol_t *platform_data = (platform_protocol_t *)buffer;
    size_t data_len = 0;
    platform_data->header = PLATFORM_PROTOCOL_HEADER;
    get_device_id(platform_data->dev_id, RADAR_OUTGOING);
    get_platform_time_stamp(platform_data->time_stamp);
    platform_data->type = 0x04;

    *(uint16_t *)platform_data->data = relay_num;
    memcpy(platform_data->data + 2, relay_data, relay_num * sizeof(platform_protocol_pole_relay_data_t));
    data_len = offsetof(platform_protocol_t, data) + 2 + relay_num * sizeof(platform_protocol_pole_relay_data_t);
    *(uint16_t *)(buffer + data_len) = PLATFORM_PROTOCOL_TAIL;
    return data_len + 2;
}

size_t pack_platform_static_data(char *buffer, radar_packet_80_t *radar_data, uint8_t dev_type)
{
    platform_protocol_t *platform_data = (platform_protocol_t *)buffer;
    platform_protocol_static_t *static_data = (platform_protocol_static_t *)platform_data->data;
    size_t data_len = 0;
    platform_data->header = PLATFORM_PROTOCOL_HEADER;
    get_device_id(platform_data->dev_id, dev_type);
    get_platform_time_stamp(platform_data->time_stamp);
    platform_data->type = 0x02;

    static_data->lane_num = radar_data->header.lane_count;
    for (int i = 0; i < static_data->lane_num; i++) {
        platform_protocol_lane_t *lane = &static_data->lane[i];
        data_80_body_t *body = &radar_data->body[i];
        lane->lane_id = body->way_id;
        lane->lane_name = way_type_to_platform(body->way_id);
        lane->cycle = radar_data->header.flow_cycle;
        lane->small_car_num = body->c_flow_rate_small;
        lane->middle_car_num = body->b_flow_rate_mid;
        lane->big_car_num = body->a_flow_rate_big;
        memset(lane->reserved, 0, sizeof(lane->reserved));
        lane->avg_time_use_rate = body->avg_time_use_rate * 10;
        lane->avg_space_use_rate = body->statistic_85_Speed * 10;
        lane->avg_speed = body->avg_flow_rate_vehicle * 10;
        lane->avg_dis_time = body->avg_dis_time * 100;
    }
    data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_static_t, lane) + static_data->lane_num * sizeof(platform_protocol_lane_t);
    *(uint16_t *)(buffer + data_len) = PLATFORM_PROTOCOL_TAIL;
    return data_len + 2;
}

size_t pack_platform_event_data(char *buffer, radar_packet_84_t *radar_data, uint8_t *time_stamp, uint8_t dev_type)
{
    platform_protocol_t *platform_data = (platform_protocol_t *)buffer;
    size_t data_len = 0;
    platform_data->header = PLATFORM_PROTOCOL_HEADER;
    get_device_id(platform_data->dev_id, dev_type);
    get_platform_time_stamp(platform_data->time_stamp);
    platform_data->type = 0x03;

    data_84_header_t *header = &radar_data->header;
    uint8_t event_type = event_type_map[header->event_type];
    if (event_type == 0) {
        return 0;
    }
    platform_protocol_event_t *event_data = (platform_protocol_event_t *)platform_data->data;
    data_84_body_t *body = &radar_data->body;
    event_data->event_type = event_type;
    // timestamp_format_conversion((const char *)time_stamp, (char *)event_data->time_stamp);
    get_platform_time_stamp(event_data->time_stamp);
    event_data->is_single = 0;
    memset(event_data->licence, 0, sizeof(event_data->licence));
    memset(event_data->obj_id, 0, sizeof(event_data->obj_id));
    memcpy(event_data->obj_id, &time_stamp[3], 3);
    event_data->obj_type = 0;
    memset(event_data->obj_color, 0, sizeof(event_data->obj_color));
    if (radar_data->header.event_type == 0x41 || radar_data->header.event_type == 0x42) {
        traffic_jam_t traffic_jam = {0};
        event_data->lane_num = lane_to_index(radar_data->body.tj.test_num) + 1;
        event_data->obj_speed = 0;
        traffic_jam.avg_speed = radar_data->body.tj.lane_averagev;
        traffic_jam.traffic_jam_start = radar_data->body.tj.traffic_jam_start;
        traffic_jam.traffic_jam_end = radar_data->body.tj.traffic_jam_end;
        traffic_jam.traffic_jam_length = radar_data->body.tj.traffic_jam_length;
        traffic_jam.traffic_jam_start_longitude = radar_data->body.tj.start_longitude;
        traffic_jam.traffic_jam_start_latitude = radar_data->body.tj.start_latitude;
        traffic_jam.traffic_jam_end_longitude = radar_data->body.tj.end_longitude;
        traffic_jam.traffic_jam_end_latitude = radar_data->body.tj.end_latitude;
        memcpy(event_data->traffic_jam, &traffic_jam, sizeof(traffic_jam));
        data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_event_t, traffic_jam) + sizeof(traffic_jam);
    }
    else if (radar_data->header.event_type == 0x43) {
        traffic_jam2_t traffic_jam2 = {0};
        event_data->obj_speed = 0;
        traffic_jam2.traffic_jam_length = radar_data->body.tj2.traffic_jam_length;
        traffic_jam2.congestion_level = radar_data->body.tj2.congestion_level;
        traffic_jam2.is_overflow = radar_data->body.tj2.is_overflow;

        event_data->dist_x = radar_data->body.tj2.start_x;
        event_data->dist_y = radar_data->body.tj2.start_y;
        event_data->lane_num = lane_to_index(radar_data->body.tj2.lane_num) + 1;

        memcpy(event_data->traffic_jam, &traffic_jam2, sizeof(traffic_jam2));
        data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_event_t, traffic_jam) + sizeof(traffic_jam2);
    }
    else {
        event_data->lane_num = lane_to_index(radar_data->body.va.obj_lane) + 1;
        event_data->obj_speed = radar_data->body.va.obj_speed;
        memcpy(&event_data->obj_id[3], &radar_data->body.va.obj_id, 2);
        event_data->obj_type = radar_data->body.va.obj_type;
        event_data->dist_x = radar_data->body.va.obj_dist_x_low;
        event_data->dist_y = radar_data->body.va.obj_dist_y_low;
        if (event_data->event_type == ABNOR_CHANGE || event_data->event_type == ACCELERATION) {
            event_data->traffic_jam[0] = radar_data->body.va.reserve2[0];
            event_data->traffic_jam[1] = radar_data->body.va.reserve2[1];
            data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_event_t, traffic_jam) + 2;
        }
        if (event_data->event_type == VEHICLE_COLLISION) {
            event_data->traffic_jam[0] = 2;
            data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_event_t, traffic_jam) + 1;
        }
        else {
            data_len = offsetof(platform_protocol_t, data) + offsetof(platform_protocol_event_t, traffic_jam);
        }
        event_data->is_single = 1;
    }

    *(uint16_t *)(buffer + data_len) = PLATFORM_PROTOCOL_TAIL;
    return data_len + 2;
}

size_t pack_pole_relay_data(radar_obj_info_t *radar_obj_info, platform_protocol_pole_relay_data_t *relay_data, size_t obj_num, uint8_t dev_type)
{
    if (radar_obj_info == NULL) {
        return obj_num;
    }
    struct tm timeinfo;
    int32_t i_longitude = 0, i_latitude = 0;
    struct_info_t *struct_info = NULL;
    relay_t *relay = NULL;

    get_device_id(relay_data->dev_id, dev_type);
    get_platform_time_stamp(relay_data->time_stamp);
    relay_data->lane_id = radar_obj_info->lane + 1;
    relay_data->lane_type = way_type_to_platform(radar_obj_info->lane);
    relay_data->position_x = radar_obj_info->dist_x;
    relay_data->position_y = radar_obj_info->dist_y;
    relay_data->speed = radar_obj_info->speed_y * 10;
    relay_data->length = radar_obj_info->length;
    i_longitude = radar_obj_info->longitude * 1e7;
    i_latitude = radar_obj_info->latitude * 1e7;
    relay_data->longitude = (((int64_t)i_longitude) << 32);
    relay_data->latitude = (((int64_t)i_latitude) << 32);

    i_latitude = radar_obj_info->speed_latitude * 1e7;
    i_longitude = radar_obj_info->speed_longitude * 1e7;
    relay_data->speed_latitude = (((int64_t)i_longitude) << 32);
    relay_data->speed_longitude = (((int64_t)i_latitude) << 32);
    relay_data->wheel_num = 4;
    relay_data->plate_length = 12;
    relay_data->guid_length = 20;
    relay_data->master_type_length = 0;
    relay_data->slave_type_length = 0;

    relay_data->type = radar_obj_info->type;
    relay_data->plate_color = 0;
    relay_data->car_color = 0;
    copy_str_with_padding(relay_data->plate, SPACE_PLATE_LICENCE, 12);
    copy_str_with_padding(relay_data->guid, "", 20);

    char *video_guid = get_video_by_radar(radar_obj_info->id, dev_type);
    if (video_guid) {
        struct_info = get_struct_info_by_guid(video_guid, dev_type);
        if (struct_info) {
            relay_data->type = struct_info->car_type;
            relay_data->plate_color = plate_color_to_platform(struct_info->plate_color);
            copy_str_with_padding(relay_data->plate, struct_info->plate_licence, 12);
            relay_data->car_color = struct_info->car_color;
            relay_data->toll_vehicle_type = struct_info->car_type_toll;
            memcpy(relay_data->guid, struct_info->guid, 20);
            relay_data->structured_data_flag = 1;
        }
    }
    relay_data->id = radar_obj_info->id;

    obj_num++;
    return obj_num;
}

bool check_platform_packet(char *buffer, int length, platform_protocol_t *platform_data, int *offset)
{
    int pos = 0;
    // 1. 从头开始查找包头

    while (pos <= length - 2) {
        uint16_t head = *(uint16_t *)(buffer + pos);
        if (head == PLATFORM_PROTOCOL_HEADER)
            break;
        pos++;
    }
    if (pos > length - 2) {
        // printf("Header not found\n");
        return false;
    }
    int packetStart = pos;
    // 2. 从包头位置开始查找包尾（假定包尾是 2 字节）
    int tailPos = -1;
    for (int i = packetStart; i <= length - 2; i++) {
        uint16_t tail = *(uint16_t *)(buffer + i);
        if (tail == PLATFORM_PROTOCOL_TAIL) {
            tailPos = i;
            break;
        }
    }
    if (tailPos < 0) {
        // printf("Tail not found\n");
        return false;
    }
    // 3. 计算包的总长度：从 packetStart 到 tailPos+2
    int packetLength = tailPos + 2 - packetStart;

    // 此处需要保证 packetLength 大于 header 部分长度 + 2
    size_t mini_len = 6;
    if (packetLength < mini_len) {
        // printf("Packet too short\n");
        return false;
    }
    if (packetLength == mini_len) {
        *offset = tailPos + 2;
        platform_data->type = 0x00;
        return true;
    }
    // 4. 拷贝数据到 platform_data 中
    memcpy(platform_data, buffer + packetStart, packetLength);
    // 5. 设置 offset 为包尾后面的位置
    *offset = tailPos + 2;
    return true;
}

// 处理平台4号协议数据，用来获取上一杆发送的接力数据
static void analysis_4_packet(char *buffer, size_t length)
{
    uint16_t relay_num = *(uint16_t *)buffer;
    int16_t offset = 2;
    uint8_t plate_length = 0;
    char *plate = NULL;
    uint8_t guid_length = 0;
    char *guid = NULL;
    uint8_t master_type_length = 0;
    char *master_type = NULL;
    uint8_t slave_type_length = 0;
    char *slave_type = NULL;
    char time_stamp[64] = {0};
    char current_time[64] = {0};

    platform_protocol_pole_relay_data_t *relay_data = (platform_protocol_pole_relay_data_t *)(buffer + offset);
    relay_t relay = {0};
    for (int i = 0; i < relay_num; i++) {
        relay.update_time = change_platform_time_stamp_to_milliseconds(relay_data->time_stamp);
        relay.relay_id = relay_data->id;
        relay.radar_obj_info.id = relay.relay_id;
        relay.radar_obj_info.type = relay_data->type;
        relay.radar_obj_info.lane = relay_data->lane_id - 1;
        relay.radar_obj_info.dist_x = relay_data->position_x - g_pole_distance;
        relay.radar_obj_info.dist_y = relay_data->position_y - g_pole_distance;
        relay.first_occurrence_pos_x = relay.radar_obj_info.dist_x;
        relay.first_occurrence_pos_y = relay.radar_obj_info.dist_y;
        relay.radar_obj_info.speed_y = relay_data->speed > 0 ? relay_data->speed / 10 : -relay_data->speed / 10;
        relay.radar_obj_info.length = relay_data->length;
        relay.radar_obj_info.longitude = (double)relay_data->longitude / 1e7;
        relay.radar_obj_info.latitude = (double)relay_data->latitude / 1e7;
        relay.radar_obj_info.speed_latitude = (double)relay_data->speed_latitude / 1e7;
        relay.radar_obj_info.speed_longitude = (double)relay_data->speed_longitude / 1e7;

        relay.video_obj_info.car_color = relay_data->car_color;
        relay.video_obj_info.car_type = relay_data->type;
        relay.video_obj_info.plate_color = relay_data->plate_color;
        relay.video_obj_info.car_type_toll = relay_data->toll_vehicle_type;

        offset += offsetof(platform_protocol_pole_relay_data_t, plate_length);
        plate_length = *(uint8_t *)(buffer + offset);
        plate = (char *)(buffer + offset + 1);

        offset += plate_length + 1;
        guid_length = *(uint8_t *)(buffer + offset);
        guid = (char *)(buffer + offset + 1);

        offset += guid_length + 1;
        master_type_length = *(uint8_t *)(buffer + offset);
        master_type = (char *)(buffer + offset + 1);

        offset += master_type_length + 1;
        slave_type_length = *(uint8_t *)(buffer + offset);
        slave_type = (char *)(buffer + offset + 1);

        relay.dis_diff = 0x7FFFFFFF;
        memcpy(relay.video_obj_info.plate_licence, plate, plate_length);
        relay.video_obj_info.plate_licence[plate_length] = '\0';
        memcpy(relay.video_obj_info.guid, guid, guid_length);
        relay.video_obj_info.guid[guid_length] = '\0';
        append_pole_relays_queue(&relay);
        relay_data = (platform_protocol_pole_relay_data_t *)(buffer + offset);
        g_pole_relay_count++;

        // if (relay.video_obj_info.car_color != 0) {
        printf("\n\033[0;33m接收到上一杆数据, 车辆ID:0x%04X 车辆类型: %s, 车辆颜色: %s, 车牌: %s,guid: %s, 车距: %d, 速度: %d, 时间戳:%s, 当前时间:%s, 总接力数:%d\033[0m\n",
               relay.relay_id,
               get_car_type(relay_data->car_color, relay.radar_obj_info.type),
               get_color_by_code(relay.video_obj_info.car_color),
               relay.video_obj_info.plate_licence,
               relay.video_obj_info.guid,
               relay.radar_obj_info.dist_y,
               relay.radar_obj_info.speed_y,
               format_time_ms(relay.update_time, time_stamp, sizeof(time_stamp)),
               get_current_time_string(current_time, sizeof(current_time)),
               g_pole_relay_count);
        // }
    }
}

// 处理平台5号协议数据,用来获取前杆的距离
static void analysis_5_packet(char *buffer, size_t length)
{
    uint16_t device_num = *(uint16_t *)buffer;
    printf("设备数量: %d\n", device_num);
    platform_protocol_dev_info_t *dev_infos = (platform_protocol_dev_info_t *)malloc(sizeof(platform_protocol_dev_info_t) * device_num);
    if (dev_infos == NULL) {
        return;
    }
    int16_t offset = 2;
    int len;
    uint8_t device_id[10];
    get_device_id(device_id, RADAR_INCOMING);
    printf("自身设备ID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
           device_id[0], device_id[1], device_id[2], device_id[3], device_id[4],
           device_id[5], device_id[6], device_id[7], device_id[8], device_id[9]);
    for (int i = 0; i < device_num; i++) {
        memcpy(&dev_infos[i], buffer + offset, sizeof(platform_protocol_dev_info_t));
        offset += sizeof(platform_protocol_dev_info_t);
        len = buffer[offset];
        offset += len + 1;
        len = buffer[offset];
        offset += len + 1;
    }

    int direction = 0;
    int serial_num = 0;
    int spacing = 0;
    int index = -1;
    printf("----------------------------------------------\n");
    for (int i = 0; i < device_num; i++) {
        if (i == index) {
            continue;
        }
        printf("设备ID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X, 方向: %d, 序列号: %d, 间距: %d\n",
               dev_infos[i].device_id[0], dev_infos[i].device_id[1], dev_infos[i].device_id[2],
               dev_infos[i].device_id[3], dev_infos[i].device_id[4], dev_infos[i].device_id[5],
               dev_infos[i].device_id[6], dev_infos[i].device_id[7], dev_infos[i].device_id[8],
               dev_infos[i].device_id[9], dev_infos[i].device_direction, dev_infos[i].device_serial_num,
               dev_infos[i].device_spacing);
        if (memcmp(dev_infos[i].device_id, device_id, 10) == 0) {
            direction = dev_infos[i].device_direction;
            serial_num = dev_infos[i].device_serial_num;
            index = i;
            i = -1;
            printf("找到了自己的设备, 方向: %d, 序列号: %d, 间距: %d\n",
                   dev_infos[i].device_direction, dev_infos[i].device_serial_num, dev_infos[i].device_spacing);
            continue;
        }
        // if (direction == dev_infos[i].device_direction && (serial_num - 1) == dev_infos[i].device_serial_num) {
        if ((serial_num - 1) == dev_infos[i].device_serial_num) {
            g_pole_distance = dev_infos[i].device_spacing * 10;
            printf("找的了自己的上一个设备, 方向: %d, 序列号: %d, 间距: %d\n",
                   dev_infos[i].device_direction, dev_infos[i].device_serial_num, dev_infos[i].device_spacing);
            break;
        }
    }
    printf("----------------------------------------------\n");
}

void analysis_platform_buffer(char *buffer, int length)
{
    platform_protocol_t platform_data = {0};
    int packet_len = 0;
    if (!g_config.need_pole_relay)
        return;
    // print_hex_buffer(buffer, length);
    while (check_platform_packet(buffer, length, &platform_data, &packet_len) == true) {
        switch (platform_data.type) {
            case 0x04:
                analysis_4_packet(platform_data.data, packet_len);
                break;
            case 0x05:
                analysis_5_packet(platform_data.data, packet_len);
                break;
            default:
                // 心跳包
                break;
        }
        length -= packet_len;
        buffer += packet_len;
        if (length <= 0) {
            break;
        }
    }
}

char *get_post_image_url()
{
    static char url[128] = {0};
    sprintf(url, "http://%s:12346/holoNet/edge/uploadImg", g_config.shanma_server_ip);
    return url;
}

void send_image_to_platform(char *guid, char *image, uint8_t dev_type)
{
    uint8_t device_id[10] = {0};
    get_device_id(device_id, dev_type);
    char id_string[21] = {0};
    bytes_to_hex_string(device_id, 10, id_string, sizeof(id_string));

    // Create JSON object
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "base64", image);
    cJSON_AddStringToObject(root, "deviceNum", id_string);
    cJSON_AddStringToObject(root, "id", guid);
    cJSON_AddNumberToObject(root, "imgType", 0);
    // Convert JSON object to string
    char *json_string = cJSON_Print(root);
    if (json_string == NULL) {
        fprintf(stderr, "Failed to create JSON string\n");
        cJSON_Delete(root);
        return;
    }

    // Initialize cURL
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();
    if (curl) {
        // Set cURL options
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_URL, get_post_image_url());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_string);
        curl_easy_setopt(curl, CURLOPT_POST, 1L);  // 启用 POST 方法

        // Perform the request
        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }

        // Cleanup
        curl_easy_cleanup(curl);
    }

    // Free JSON string and object
    free(json_string);
    cJSON_Delete(root);
}